/**
 * 一、请说出下列最终的执行结果,并解 释为什么。
 */
var a = [];
for (var i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6]();
// ------------------------------
/* 输出：10
因为 for 函数中使用 var 关键字声明了变量 i，使得变量 i 被提升至当前作用域的最顶层，即全局作用域，而for循环中的函数声明并不是立即调用，所以最后 a[6]() 触发的函数中变量 i 为全局变量中被累加了九次后值为 10 的 i。 */

/**
 * 二、请说出下列最终的执行结果,并解 释为什么。
 */
var tmp = 123;

if (true) {
  console.log(tmp);
  let tmp;
}
// ------------------------------
/* 输出：ReferenceError
由于在 if 产生的块级作用域中使用了 let 关键字声明了与外部同名的 tmp 变量，造成暂时性死区，使得在 let 定义 tmp 变量前不可对 tmp 进行任何的操作，而这里的 console.log 方法使用它作为参数使用违反了这一规定，故报错 */

/**
 * 三、结合ES6新语法,用最简单的方式 找出数组中的最小值
 */
var arr = [12, 34, 32, 89, 4];
// ------------------------------
const arrMin = Math.min(...arr);

/**
 * 四、请详细说明var,let, const三种声明变量的方式之间的具体差别。
 */
/* var 声明的变量作用域会被提升至当前作用域最顶层，统一作用域下，在使用关键字 var 声明变量之前该变量名可用，不过返回值为 undefined
let 声明的变量的作用域仅为当前的块作用域，且变量不可在被声明前调用，如果在块级作用域中使用 let 定义了和外层同名变量，则产生暂时性死区，在 let 声明执行之前该变量不可进行任何操作
const 和let类似，同样作用域为当前块作用域，不可提前被调用，且只能在初始化声明变量时赋值 */

/**
 * 五、请说出下列代码最终输出的结果, 并解释为什么。
 */
var a = 10;
var obj = {
  a: 20,
  fn() {
    setTimeout(() => {
      console.log(this.a);
    });
  },
};
obj.fn();
// ------------------------------
/* 输出：20
因为 obj.fn 中 setTimeout 的回调函数使用的是箭头函数进行声明，使得函数体内部的 this 永远指向当前所在对象，即 obj 本身，this.a 也会是 obj.a */

/**
 * 六、简述 Symbo1类型的用途。
 */
/* 
创造出一个全局唯一的值
利用不可被枚举的特性，创造对象私有属性
将普通对象转化成符合 iterable 接口的可迭代对象
 */

/**
 * 七、说说什么是浅拷贝,什么是深拷贝?
 */
/* 浅拷贝：只复制基础类型数值和引用地址的复制
深拷贝：复制基础类型值，以及对存放于堆中的引用值也进行完全的复制 */

/**
 * 八、请简述 Typescript 与 Javascript之间的关系。
 */
/* Typescript 是 Javescript 的超集 */

/**
 * 九、请谈谈你所认为的 Typescript 优缺点
 */
/* 
  优点：
    - 对IDE友好，可自动提示类型及补全
    - 使一些语法和基础逻辑错误在编译时就暴露出来
    - 支持 ECMAScript 的新特性
  缺点： 
    - 对于小型项目来说会增加不必要的代码量
    - 对三方库的支持需要持续完善
    - 有一定的学习成本
*/

/**
 * 十、描述引用计数的工作原理和优缺点
 */
/* 
  优点：
    - 发现垃圾时立刻回收（时刻监听计数是否为0）
    - 最大限度减少程序暂停（因为一直在时刻监听，所以可以在内存饱满时及时释放）
  缺点：
    - 无法回收循环引用对象
    - 时间开销大（时刻在监听&执行计数） 
*/

/**
 * 十一、描述标记整理算法的工作流程。
 */
/*
  1. 遍历所有对象找标记活动对象（是否可达）
  2. 遍历所有对象清除所有未标记活动对象
  3. 先进行内存整理，然后清除（解决清除后内存碎片化的问题）
 */

/**
 * 十二、描述V8中新生代存储区垃圾回收的流程。
 */
/*
  1. 新生代内存区分为两个相等大小的空间（使用空间为 From，空闲空间为 To）
  2. 活动对象存储于 From
  3. 标记整理后将活动对象拷贝至 To
  4. 完全释放 From
  5. From 和 To 交换空间，完成内存释放
*/

/**
 * 十三、描述增量标记算法在何时使用及工作原理。
 */
/*
  在老生代中使用增量标记进行效率优化
  将原本整段执行的标记任务拆分成多个小模块分批执行，最大限度减少对主线程的长时间阻塞。
*/
